package com.example.firstdemo.network.service

import android.util.Log
import com.example.firstdemo.Config
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Authenticator
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.Route
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import java.io.IOException
import java.net.HttpURLConnection
import java.util.concurrent.TimeUnit

val LOG_TAG = "Service"

@Serializable
data class BaseResponse<T>(
    val data: T? = null,
    val code: Int = 200,
    val msg: String = ""
)

// 认证拦截器 - 自动添加 token 到请求头
class AuthInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()

        // 如果当前没有 token 或者请求已经是认证请求，直接继续
        if (UserManager.currentToken.value.isNullOrEmpty() ||
            originalRequest.header("Authorization") != null
        ) {
            return chain.proceed(originalRequest)
        }

        // 添加认证头
        val requestWithAuth = originalRequest.newBuilder()
            .header("Authorization", "Bearer ${UserManager.currentToken.value}")
            .build()

        return chain.proceed(requestWithAuth)
    }
}

class NetworkException(
    message: String = "",
    val code: Int = 0,
    val logicCode: Int? = null,
    val responseBody: String? = null,
    val details: String? = null
) : IOException(message)


object NetworkErrorEventManager {
    private val _networkErrorEvent = MutableSharedFlow<String>()
    val networkErrorEvent: SharedFlow<String> = _networkErrorEvent.asSharedFlow()

    suspend fun emitEvent(msg: String) {
        _networkErrorEvent.emit(msg)
    }
}


class ResponseErrorInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request: Request = chain.request()
        lateinit var response: Response
        try {
            response = chain.proceed(request)
        } catch (e: IOException) {
            Log.e(LOG_TAG, "网络连接失败${e.message}")
            CoroutineScope(Dispatchers.IO).launch {
                NetworkErrorEventManager.emitEvent("网络连接失败")
            }
            throw NetworkException("网络连接失败", details = e.message)
        } catch (e: Exception) {
            Log.e(LOG_TAG, "未知错误${e.message}")
            CoroutineScope(Dispatchers.IO).launch {
                NetworkErrorEventManager.emitEvent("未知错误${e.message}")
            }
            throw NetworkException("未知错误", details = e.message)
        }

        // 检查HTTP状态码
        if (!response.isSuccessful) {
            val errorBody = response.body?.string() ?: ""
            // 可以根据不同的状态码进行不同的处理
            when (response.code) {
                HttpURLConnection.HTTP_UNAUTHORIZED -> {
                    Log.e(LOG_TAG, "认证失败，请重新登录(${response.code})")
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent("认证失败，请重新登录(${response.code})")
                    }
                    throw NetworkException("认证失败，请重新登录(${response.code})", response.code)
                }

                HttpURLConnection.HTTP_INTERNAL_ERROR -> {
                    Log.e(LOG_TAG, "服务器内部错误，请稍后再试(${response.code})")
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent("服务器内部错误，请稍后再试(${response.code})")
                    }
                    throw NetworkException("服务器内部错误，请稍后再试", response.code)
                }

                HttpURLConnection.HTTP_NOT_FOUND -> {
                    Log.e(LOG_TAG, "资源不存在(${response.code})")
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent("资源不存在(${response.code})")
                    }
                    throw NetworkException("资源不存在(${response.code})", response.code)
                }

                else -> {
                    Log.e(LOG_TAG, "网络请求失败(${response.code}):${errorBody}")
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent("网络请求失败(${response.code})")
                    }
                    throw NetworkException(
                        "网络请求失败: ${response.code}",
                        response.code,
                        null,
                        errorBody
                    )
                }
            }
        }
        return response
    }
}

class ResponseLogicErrorInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val response: Response = chain.proceed(chain.request())
        val responseBody = response.body
        val contentType = responseBody?.contentType()
        if (contentType?.subtype?.equals("json", ignoreCase = true) == true) {
            val responseText = responseBody.string()
            // 解析为 JsonObject 以便检查 code
            val jsonObject = Json.parseToJsonElement(responseText).jsonObject
            val code = jsonObject["code"]?.jsonPrimitive?.intOrNull
            val msg = jsonObject["msg"]?.jsonPrimitive?.content ?: ""
            when (code) {
                200 -> {
                    val newResponseBody = responseText.toResponseBody(contentType)
                    return response.newBuilder().body(newResponseBody).build()
                }

                401 -> {
                    Log.e(LOG_TAG, "认证失败，请重新登录(401)")
                    CoroutineScope(Dispatchers.IO).launch {
                        AuthEventManager.emitEvent(AuthEventManager.AuthEvent.TokenExpired)
                    }
                    throw NetworkException("认证失败，请重新登录", logicCode = 401)
//                    return response.newBuilder().body(
//                        responseText.toResponseBody(responseBody.contentType())
//                    ).build()
                }

                403 -> {
                    Log.e(LOG_TAG, "当前操作没有权限(403)")
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent("当前操作没有权限")
                    }
                    throw NetworkException("当前操作没有权限", logicCode = 403)
                }

                404 -> {
                    Log.e(LOG_TAG, "访问资源不存在(404)")
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent("访问资源不存在")
                    }
                    throw NetworkException("访问资源不存在", logicCode = 404)
                }

                500 -> {
                    Log.e(LOG_TAG, msg)
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent(msg)
                    }
                    throw NetworkException(msg, logicCode = 500)
                }

                else -> {
                    Log.e(LOG_TAG, "未知错误(${code})")
                    CoroutineScope(Dispatchers.IO).launch {
                        NetworkErrorEventManager.emitEvent("未知错误(${code})")
                    }
                    throw NetworkException("未知错误", logicCode = code)
                }
            }
        }

        // 非 JSON 响应直接返回
        return response
    }
}


// Token 刷新认证器
class TokenRefreshAuthenticator : Authenticator {
    override fun authenticate(route: Route?, response: Response): Request? {
        // 这里可以实现 token 刷新逻辑
        // 如果认证失败，尝试刷新 token 并重试请求
        // 注意：这是一个复杂的功能，需要根据后端API设计来实现

        // 简单实现：返回 null 表示不尝试刷新
        return null
    }
}

object RetrofitService {
    private const val BASE_URL = Config.BASE_URL

    // JSON 配置
    private val json = Json {
        ignoreUnknownKeys = true // 忽略未知键
        isLenient = true // 宽松解析
        encodeDefaults = true // 编码默认值
    }

    // OkHttp 客户端
    private val okHttpClient: OkHttpClient by lazy {
        OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
            .addInterceptor(AuthInterceptor()) // 添加认证拦截器
            .addInterceptor(ResponseLogicErrorInterceptor()) // 逻辑错误拦截器
            .addInterceptor(ResponseErrorInterceptor()) // 网络错误拦截器
            .authenticator(TokenRefreshAuthenticator()) // 添加 token 刷新认证器
            .build()
    }

    // Retrofit 实例
    val retrofit: Retrofit by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
            .build()
    }

    // 创建服务API的泛型方法
    inline fun <reified T> create(): T = retrofit.create(T::class.java)
//    fun <T> create(serviceClass: Class<T>): T {
//        return retrofit.create(serviceClass)
//    }
}